#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>

// 设备名称
#define DEVICE_NAME "simple_char_driver"
#define CLASS_NAME  "simple_char_class"

// 缓冲区大小
#define BUFFER_SIZE 1024

// 全局变量
static int major_number;
static char buffer[BUFFER_SIZE] = {0};
static struct class* simple_class = NULL;
static struct device* simple_device = NULL;
static struct cdev simple_cdev;
static atomic_t open_count = ATOMIC_INIT(0);

// 函数声明
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);

// 文件操作结构
static struct file_operations fops = {
    .open = dev_open,
    .read = dev_read,
    .write = dev_write,
    .release = dev_release,
};

// 模块初始化函数
static int __init simple_char_driver_init(void) {
    printk(KERN_INFO "SimpleCharDriver: 初始化驱动\n");

    // 注册字符设备，获取主设备号
    major_number = register_chrdev(0, DEVICE_NAME, &fops);
    if (major_number < 0) {
        printk(KERN_ALERT "SimpleCharDriver: 注册设备失败\n");
        return major_number;
    }
    printk(KERN_INFO "SimpleCharDriver: 注册成功，主设备号: %d\n", major_number);

    // 创建设备类
    simple_class = class_create(THIS_MODULE, CLASS_NAME);
    if (IS_ERR(simple_class)) {
        unregister_chrdev(major_number, DEVICE_NAME);
        printk(KERN_ALERT "SimpleCharDriver: 创建设备类失败\n");
        return PTR_ERR(simple_class);
    }
    printk(KERN_INFO "SimpleCharDriver: 设备类创建成功\n");

    // 创建设备节点
    simple_device = device_create(simple_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);
    if (IS_ERR(simple_device)) {
        class_destroy(simple_class);
        unregister_chrdev(major_number, DEVICE_NAME);
        printk(KERN_ALERT "SimpleCharDriver: 创建设备节点失败\n");
        return PTR_ERR(simple_device);
    }
    printk(KERN_INFO "SimpleCharDriver: 设备节点创建成功\n");

    // 初始化字符设备
    cdev_init(&simple_cdev, &fops);
    if (cdev_add(&simple_cdev, MKDEV(major_number, 0), 1) < 0) {
        device_destroy(simple_class, MKDEV(major_number, 0));
        class_destroy(simple_class);
        unregister_chrdev(major_number, DEVICE_NAME);
        printk(KERN_ALERT "SimpleCharDriver: 添加cdev失败\n");
        return -1;
    }

    return 0;
}

// 模块退出函数
static void __exit simple_char_driver_exit(void) {
    cdev_del(&simple_cdev);
    device_destroy(simple_class, MKDEV(major_number, 0));
    class_unregister(simple_class);
    class_destroy(simple_class);
    unregister_chrdev(major_number, DEVICE_NAME);
    printk(KERN_INFO "SimpleCharDriver: 驱动已卸载\n");
}

// 设备打开函数
static int dev_open(struct inode *inodep, struct file *filep) {
    if (atomic_cmpxchg(&open_count, 0, 1)) {
        return -EBUSY;
    }
    printk(KERN_INFO "SimpleCharDriver: 设备已打开\n");
    return 0;
}

// 设备读取函数
static ssize_t dev_read(struct file *filep, char *buffer_to_user, size_t len, loff_t *offset) {
    int error_count = 0;
    
    // 将缓冲区数据复制到用户空间
    error_count = copy_to_user(buffer_to_user, buffer, len);
    
    if (error_count == 0) {
        printk(KERN_INFO "SimpleCharDriver: 读取了 %zu 个字节\n", len);
        return len;
    } else {
        printk(KERN_INFO "SimpleCharDriver: 复制到用户空间失败 %d\n", error_count);
        return -EFAULT;
    }
}

// 设备写入函数
static ssize_t dev_write(struct file *filep, const char *buffer_from_user, size_t len, loff_t *offset) {
    // 将用户空间数据复制到缓冲区
    if (len > BUFFER_SIZE) {
        len = BUFFER_SIZE;
    }
    
    memset(buffer, 0, BUFFER_SIZE);
    memcpy(buffer, buffer_from_user, len);
    
    printk(KERN_INFO "SimpleCharDriver: 写入了 %zu 个字节\n", len);
    printk(KERN_INFO "SimpleCharDriver: 数据: %s\n", buffer);
    
    return len;
}

// 设备关闭函数
static int dev_release(struct inode *inodep, struct file *filep) {
    atomic_set(&open_count, 0);
    printk(KERN_INFO "SimpleCharDriver: 设备已关闭\n");
    return 0;
}

// 模块元数据
module_init(simple_char_driver_init);
module_exit(simple_char_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZENrs Driver Team");
MODULE_DESCRIPTION("A simple Linux char device driver example");
MODULE_VERSION("1.0");